package com.mach.platform.sprider.dev.virdev;

import com.mach.platform.sprider.dev.UU;
import com.mach.platform.sprider.getter.CmdMainWork;
import com.mach.platform.sprider.getter.DevFactory;
import com.mach.platform.sprider.getter.GeneralDev;
import com.mach.platform.sprider.getter.GeneralModbusDev;
import com.mach.platform.sprider.getter.DataLogService;
import com.mach.platform.util.SqlHelper;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;

@Slf4j
public class PressCompAirMainKeeperAutoFullCtrl extends GeneralModbusDev implements VirDev {

    private Map<Object,Object> devPropsMap;


    private SqlHelper sqlHelper;
    private  DataLogService dataLogService;
    private  Map<String, Object> devInfoMap;
    private boolean isOpen = false;
    private GeneralDevCtx[] lengGanjisGroup;
    private SimpleValveDev[] lengGanjiWaterValvesGroup;
    private SimpleValveDev[] lengGanjiAirValvesGroup;
    private GeneralDevCtx[] mainsGroup;
    private long lastCmdTime = 0;
    private SimpleValveDev[] mainWaterValvesGroup;
//    private  Integer devId;


    public PressCompAirMainKeeperAutoFullCtrl(Map<String, Object> devInfoMap, SqlHelper sqlHelper, DataLogService dataLogService) throws SQLException {
        super(devInfoMap, sqlHelper, dataLogService);

        this.devInfoMap = devInfoMap;

        this.sqlHelper = sqlHelper;

        this.dataLogService = dataLogService;

        this.devPropsMap = sqlHelper.getMapFrTable("name", "value",
                "select name, value value " +
                        " from iot_dev_prop prop " +
                        " where prop.dev_id=" + this.devId);




    }

    private void initCtrInfo(){

        this.lengGanjisGroup = new GeneralDevCtx[6];
        this.lengGanjisGroup[0] = new GeneralDevCtx( (DbChannelSwitchDev)DevFactory.getById(117)); //1#冷干机
        this.lengGanjisGroup[1] = new GeneralDevCtx( (DbChannelSwitchDev)DevFactory.getById(120)); //2#冷干机
        this.lengGanjisGroup[2] = new GeneralDevCtx( (DbChannelSwitchDev)DevFactory.getById(123)); //3#冷干机
        this.lengGanjisGroup[3] = new GeneralDevCtx( (DbChannelSwitchDev)DevFactory.getById(126)); //4#冷干机
        this.lengGanjisGroup[4] = new GeneralDevCtx( (DbChannelSwitchDev)DevFactory.getById(129)); //5#冷干机
        this.lengGanjisGroup[5] = new GeneralDevCtx( (DbChannelSwitchDev)DevFactory.getById(140)); //6#冷干机

        this.lengGanjiWaterValvesGroup = new SimpleValveDev[6];
        this.lengGanjiWaterValvesGroup[0] = (SimpleValveDev)DevFactory.getById(119); //1#冷干机
        this.lengGanjiWaterValvesGroup[1] = (SimpleValveDev)DevFactory.getById(122); //2#冷干机
        this.lengGanjiWaterValvesGroup[2] = (SimpleValveDev)DevFactory.getById(125); //3#冷干机
        this.lengGanjiWaterValvesGroup[3] = (SimpleValveDev)DevFactory.getById(128); //4#冷干机
        this.lengGanjiWaterValvesGroup[4] = (SimpleValveDev)DevFactory.getById(131); //5#冷干机
        this.lengGanjiWaterValvesGroup[5] = (SimpleValveDev)DevFactory.getById(133); //6#冷干机


        this.lengGanjiAirValvesGroup = new SimpleValveDev[6];
        this.lengGanjiAirValvesGroup[0] = (SimpleValveDev)DevFactory.getById(118); //1#冷干机
        this.lengGanjiAirValvesGroup[1] = (SimpleValveDev)DevFactory.getById(121); //2#冷干机
        this.lengGanjiAirValvesGroup[2] = (SimpleValveDev)DevFactory.getById(124); //3#冷干机
        this.lengGanjiAirValvesGroup[3] = (SimpleValveDev)DevFactory.getById(127); //4#冷干机
        this.lengGanjiAirValvesGroup[4] = (SimpleValveDev)DevFactory.getById(130); //5#冷干机
        this.lengGanjiAirValvesGroup[5] = (SimpleValveDev)DevFactory.getById(132); //6#冷干机

        this.mainsGroup = new GeneralDevCtx[7];
        this.mainsGroup[0] = new GeneralDevCtx( (GeneralModbusDev)DevFactory.getById(142)); //1#空压机
        this.mainsGroup[1] = new GeneralDevCtx( (GeneralModbusDev)DevFactory.getById(143)); //2#空压机
        this.mainsGroup[2] = new GeneralDevCtx( (GeneralModbusDev)DevFactory.getById(144)); //3#空压机
        this.mainsGroup[3] = new GeneralDevCtx( (GeneralModbusDev)DevFactory.getById(145)); //4#空压机
        this.mainsGroup[4] = new GeneralDevCtx( (GeneralModbusDev)DevFactory.getById(147)); //1#螺杆机
        this.mainsGroup[5] = new GeneralDevCtx( (GeneralModbusDev)DevFactory.getById(148)); //2#螺杆机
        this.mainsGroup[6] = new GeneralDevCtx( (GeneralModbusDev)DevFactory.getById(146)); //3#螺杆机

        this.mainWaterValvesGroup = new SimpleValveDev[6];
        this.mainWaterValvesGroup[0] = (SimpleValveDev)DevFactory.getById(105); //1#空压机
        this.mainWaterValvesGroup[1] = (SimpleValveDev)DevFactory.getById(107); //2#空压机
        this.mainWaterValvesGroup[2] = (SimpleValveDev)DevFactory.getById(108); //3#空压机
        this.mainWaterValvesGroup[3] = (SimpleValveDev)DevFactory.getById(109); //4#空压机
        this.mainWaterValvesGroup[4] = (SimpleValveDev)DevFactory.getById(111); //1#螺杆机
        this.mainWaterValvesGroup[5] = (SimpleValveDev)DevFactory.getById(112); //2#螺杆机
        this.mainWaterValvesGroup[6] = (SimpleValveDev)DevFactory.getById(110); //3#螺杆机


    }

    @Override
    protected void pick() {
        try {
            this.devPropsMap = sqlHelper.getMapFrTable("name", "value",
                    "select name, value value " +
                            " from iot_dev_prop prop " +
                            " where prop.dev_id=" + this.devId);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        Integer auto = Integer.parseInt((String)this.devPropsMap.get("auto"));
        if(auto == 1){
            this.isOpen = true;
        }else{
            this.isOpen = false;
        }
        if(!this.isOpen ){
            UU.sleep(1000*5);
            return;
        }else{

        }

        long cur = System.currentTimeMillis();
        if( (cur - this.lastCmdTime) <  1000*60 * 20){
            UU.sleep(1000*30);
            return;
        }
        initCtrInfo();

        Double upValue = Double.parseDouble((String)this.devPropsMap.get("setUp"));
        Double downValue = Double.parseDouble((String)this.devPropsMap.get("setDown"));

        GeneralDev pressDev = DevFactory.getById(102); //压力传感器

        try {
            Double press = (Float) pressDev.getValueByCollName("压力") * 1.0;

            GeneralDevCtx dev = null;
            if(press < downValue){ //超下限
                //需要开机
                //找一台(主机)非故障，然后找出运行时间最短，当天开启次数最少
                GeneralDevCtx mainCanBeUsed = this.findCanBeOpenedMain();
                //开对应阀门，先主机阀门，然后是主机阀门，然后是冷干机阀门
                //主机水阀门
                SimpleValveDev mainWaterValv = this.mainWaterValvesGroup[mainCanBeUsed.devIx.intValue()];
                this.openValv(mainWaterValv);
                CmdMainWork.commitCmd(mainCanBeUsed.getDevId(),"open","");
                this.lastCmdTime = System.currentTimeMillis();

                if(  mainCanBeUsed == null){//主机为空不操作
                    return;
                }
                //看看冷干机数量对不对，不对则需要多台
                //找一台(冷干机)非故障，然后找出运行时间最短，当天开启次数最少
                GeneralDevCtx cool = this.findBeOpenCoolDev(mainCanBeUsed);
                if(cool==null &&  mainCanBeUsed == null){//主机为空不操作
                    return;
                }

                //冷干机进水阀
                SimpleValveDev coolWaterValv = this.lengGanjiWaterValvesGroup[cool.devIx.intValue()];
                //冷干机进气阀
                SimpleValveDev coolAirValv = this.lengGanjiAirValvesGroup[cool.devIx.intValue()];

                this.openValv(coolWaterValv);
                this.openValv(coolAirValv);
                this.openCool(cool);

            }
            if(press > upValue){ //超上限
//                CmdMainWork.commitCmd(dev.getDevId(),"close","");
                //找一台(主机)非故障，然后找出运行时间最短长，当天开启次数最多
                GeneralDevCtx mainCanBeUsed = this.findCanBeClosedMain();
                if(mainCanBeUsed == null)return;
                CmdMainWork.commitCmd(mainCanBeUsed.getDevId(),"close","");
                this.lastCmdTime = System.currentTimeMillis();

                //看看冷干机数量对不对，不对则需要关台
                //找一台(冷干机)非故障，然后找出运行时间最长，当天开启次数最多
                GeneralDevCtx cool = this.findBeCloseCoolDev(mainCanBeUsed);
                if(cool==null &&  mainCanBeUsed == null){//主机为空不操作
                    return;
                }
                //冷干机进水阀
                SimpleValveDev coolWaterValv = this.lengGanjiWaterValvesGroup[cool.devIx.intValue()];
                //冷干机进气阀
                SimpleValveDev coolAirValv = this.lengGanjiAirValvesGroup[cool.devIx.intValue()];

                this.openValv(coolWaterValv);
                this.openValv(coolAirValv);
                this.openCool(cool);


            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (OpenFailException e) {
            e.printStackTrace();
        }


    }

    private void openCool(GeneralDevCtx cool) throws SQLException {
        CmdMainWork.commitCmd(cool.getDevId(),"stopOpen","");
    }

    private void openValv(SimpleValveDev valve) throws OpenFailException {
        long waitTime = 1000 * 40;
        try {
            CmdMainWork.commitCmd(valve.getDevId(),"startOpen","");

            long startTime = System.currentTimeMillis();
            boolean isWait = true;
            while(isWait){
                UU.sleep(1000);
                Short status = (Short)valve.getValueByCollName("开到位");
                if(status == 1){
                    isWait = false;
                    break;
                }
                long now = System.currentTimeMillis();
                long dt = now - startTime;
                if(dt > waitTime){//打开超时
                    CmdMainWork.commitCmd(valve.getDevId(),"stopOpen","");
                    isWait = false;
                    throw new OpenFailException
                            ("Open value Fail devId="+ valve.getDevId() + "e=打开阀门超时");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new OpenFailException
                    ("Open value Fail devId="+ valve.getDevId() + "e="+ e.getLocalizedMessage());
        }
    }

    private GeneralDevCtx findBeOpenCoolDev(GeneralDev mainCanBeUsed) {
        int runCntOfMain = this.getRunningCntOfMain();
        int runCntOfCool = this.getRunningCntOfCool();

        GeneralDevCtx resultDev  = null;
        if(runCntOfCool >= runCntOfMain){//不需要启动
            return null;
        }

        resultDev = (GeneralDevCtx)this.findCanBeOpenedCool();
        return resultDev;
    }
    private GeneralDevCtx findBeCloseCoolDev(GeneralDev mainCanBeUsed) {
        int runCntOfMain = this.getRunningCntOfMain();
        int runCntOfCool = this.getRunningCntOfCool();

        GeneralDevCtx resultDev  = null;
        if(runCntOfCool <= runCntOfMain){//不需要启动
            return null;
        }

        resultDev = (GeneralDevCtx)this.findCanBeClosedCool();
        return resultDev;
    }

    private int getRunningCntOfMain(){
        int runCntOfMain = 0;
        for( GeneralDev tMain : this.mainsGroup ){
            Integer runStatus = null;
            try {
                runStatus = (Integer) tMain.getValueByCollName("运行状态");
                if(null != runStatus && runStatus ==1 ){//正在运行
                    ++runCntOfMain;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return runCntOfMain;
    }
    private int getRunningCntOfCool(){
        int runCntOfCool = 0;
        for( GeneralDev coolDev : this.lengGanjisGroup ){
            Integer runStatus = null;
            try {
                runStatus = (Integer) coolDev.getValueByCollName("运行状态");
                if(null != runStatus && runStatus ==1 ){//正在运行
                    ++runCntOfCool;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return runCntOfCool;
    }

    /**
     * 找一台(主机)非故障，然后找出运行时间最短，当天开启次数最少
     * @return
     */
    private GeneralDevCtx findCanBeOpenedMain() {
        GeneralDevCtx result = null;
        GeneralDev comSusDev = null;
        GeneralDev canBeOpen = null;
        Integer mixRunTime = Integer.MAX_VALUE;
        Integer mixStartCnt = Integer.MAX_VALUE;

        ArrayList<GeneralDevCtx> lowRunCntDevs = new ArrayList<GeneralDevCtx>();

        for( GeneralDevCtx tMain : this.mainsGroup ){
            Integer isFat = null;
            try {
                isFat = (Integer) tMain.getValueByCollName("是否故障");
                if(null != isFat){//通讯正常

                }else{
                    continue;
                }
                Integer startCnt = (Integer) tMain.getValueByCollName("运行次数");
                Integer runTime = (Integer) tMain.getValueByCollName("运行时间");
//                if(startCnt <= mixStartCnt && isFat != 1){
//                    mixStartCnt = startCnt;
//                }
                if(isFat != 1 && startCnt <=1 ){
                    comSusDev = tMain;
                    tMain.runCnt = startCnt;
                    tMain.runTime = runTime;
                    lowRunCntDevs.add(tMain);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        Collections.sort(lowRunCntDevs, (o1, o2) -> {
            if(o1.runCnt == o2.runCnt){
                return o1.runTime - o2.runTime;
            }
            return o1.runCnt - o2.runCnt;
        });

//        if(result == null){
//            //没有结果的话，看看通讯正常的设备也是需要的
//            result = comSusDev;
//        }

        if(lowRunCntDevs.size() > 0){
            result = lowRunCntDevs.get(0);
        }

        return result;

    }
    /**
     * 找一台(主机)运行，然后找出运行时间最长，当天开启次数最多
     * @return
     */
    private GeneralDevCtx findCanBeClosedMain() {
        GeneralDevCtx result = null;
        GeneralDev comSusDev = null;
        GeneralDev canBeOpen = null;
        Integer mixRunTime = 0;
        Integer mixStartCnt = 0;

        ArrayList<GeneralDevCtx> lowRunCntDevs = new ArrayList<GeneralDevCtx>();

        for( GeneralDevCtx tMain : this.mainsGroup ){
            Integer isFat = null;
            try {
                isFat = (Integer) tMain.getValueByCollName("运行状态");
                if(null != isFat){//通讯正常

                }else{
                    continue;
                }
                Integer startCnt = (Integer) tMain.getValueByCollName("运行次数");
                Integer runTime = (Integer) tMain.getValueByCollName("运行时间");
//                if(startCnt <= mixStartCnt && isFat != 1){
//                    mixStartCnt = startCnt;
//                }
                if(isFat != 1 && startCnt <=1 ){
                    comSusDev = tMain;
                    tMain.runCnt = startCnt;
                    tMain.runTime = runTime;
                    lowRunCntDevs.add(tMain);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        Collections.sort(lowRunCntDevs, (o1, o2) -> {
            if(o1.runCnt == o2.runCnt){
                return o2.runTime - o1.runTime;
            }
            return o2.runCnt - o1.runCnt;
        });

//        if(result == null){
//            //没有结果的话，看看通讯正常的设备也是需要的
//            result = comSusDev;
//        }

        if(lowRunCntDevs.size() > 0){
            result = lowRunCntDevs.get(0);
        }

        return result;

    }
    /**
     * 找一台(冷干机)非故障，然后找出运行时间最短，当天开启次数最少
     * @return
     */
    private GeneralDev findCanBeOpenedCool() {
        GeneralDev result = null;
        GeneralDev comSusDev = null;
        GeneralDev canBeOpen = null;
        Integer mixRunTime = Integer.MAX_VALUE;
        Integer mixStartCnt = Integer.MAX_VALUE;

        ArrayList<GeneralDevCtx> lowRunCntDevs = new ArrayList<GeneralDevCtx>();

        for( GeneralDevCtx cool : this.lengGanjisGroup ){
            Integer isFat = null;
            try {
                isFat = (Integer) cool.getValueByCollName("是否故障");
                if(null != isFat){//通讯正常

                }else{
                    continue;
                }
                Integer startCnt = (Integer) cool.getValueByCollName("运行次数");
                Integer runTime = (Integer) cool.getValueByCollName("运行时间");
//                if(startCnt <= mixStartCnt && isFat != 1){
//                    mixStartCnt = startCnt;
//                }
                if(isFat != 1 && startCnt <=1 ){
                    comSusDev = cool;
                    cool.runCnt = startCnt;
                    cool.runTime = runTime;
                    lowRunCntDevs.add(cool);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        Collections.sort(lowRunCntDevs, (o1, o2) -> {
            if(o1.runCnt == o2.runCnt){
                return o1.runTime - o2.runTime;
            }
            return o1.runCnt - o2.runCnt;
        });
        if(lowRunCntDevs.size() > 0){
            result = lowRunCntDevs.get(0);
        }

        return result;

    }
    /**
     * 找一台(冷干机)非故障，然后找出运行时间最短，当天开启次数最少
     * @return
     */
    private GeneralDev findCanBeClosedCool() {
        GeneralDev result = null;
        GeneralDev comSusDev = null;
        GeneralDev canBeOpen = null;
        Integer mixRunTime = 0;
        Integer mixStartCnt = 0;

        ArrayList<GeneralDevCtx> lowRunCntDevs = new ArrayList<GeneralDevCtx>();

        for( GeneralDevCtx cool : this.lengGanjisGroup ){
            Integer isFat = null;
            try {
                isFat = (Integer) cool.getValueByCollName("运行状态");
                if(null != isFat){//通讯正常

                }else{
                    continue;
                }
                Integer startCnt = (Integer) cool.getValueByCollName("运行次数");
                Integer runTime = (Integer) cool.getValueByCollName("运行时间");
//                if(startCnt <= mixStartCnt && isFat != 1){
//                    mixStartCnt = startCnt;
//                }
                if(isFat != 1 && startCnt <=1 ){
                    comSusDev = cool;
                    cool.runCnt = startCnt;
                    cool.runTime = runTime;
                    lowRunCntDevs.add(cool);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        Collections.sort(lowRunCntDevs, (o1, o2) -> {
            if(o1.runCnt == o2.runCnt){
                return o2.runTime - o1.runTime;
            }
            return o2.runCnt - o1.runCnt;
        });
        if(lowRunCntDevs.size() > 0){
            result = lowRunCntDevs.get(0);
        }

        return result;

    }

    private TransducerCtrDev findMostUpTransducer() {
        TransducerCtrDev tr = null;
        Integer maxFrep = null;
        TransducerCtrDev tmpDev = null;
        for( TransducerCtrDev dev : new TransducerCtrDev[10] ){
            //给定频率
            try {
                Short outFrep = (Short)dev.getValueByCollName("输出频率");
                if(outFrep == null){
                    continue;
                }else{
                     tmpDev = dev;
                }
                if(maxFrep == null){
                    maxFrep = dev.getFrep();
                }
                Integer frep = dev.getFrep();
                if(frep >= maxFrep && frep < 490){
                    maxFrep = frep;
                    tr = dev;
                }


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if(tr == null)tr = tmpDev;
        return tr;
    }


    @Override
    public void cmd(Integer cmdLogId,String cmd, String param) {

        try {
            Integer devTypeId = (Integer)this.devInfoMap.get("devTypeId");

//            Map<Object, Object> addrMap = sqlHelper.getMapFrTable("name", "valueAddr",
//                    "select name, value_addr valueAddr " +
//                            " from iot_coll_items colls " +
//                            " where colls.dev_type_id=" + devTypeId);

//            if(ctrModelValue != null && ctrModelValue.equals(1.0)){//远程
            if("open".equals(cmd) ){
                this.isOpen = true;
                sqlHelper.update("replace into iot_dev_prop(name,value,dev_id)" +
                        "value('auto','1',"+devId+")");
            }
            if("close".equals(cmd) ){
                this.isOpen = false;
                sqlHelper.update("replace into iot_dev_prop(name,value,dev_id)" +
                        "value('auto','0',"+devId+")");
            }
            if("setUp".equals(cmd) && param != null ){
                sqlHelper.update("replace into iot_dev_prop(name,value,dev_id)" +
                        "value('setUp','"+param+"',"+devId+")");
            }
            if("setDown".equals(cmd) && param != null ){
                sqlHelper.update("replace into iot_dev_prop(name,value,dev_id)" +
                        "value('setDown','"+param+"',"+devId+")");
            }

            sqlHelper.update(
                    "update iot_dev_cmd_log set resp_code=1,resp_ctx='"+EXE_SUCS_CTX+"' where id=" + cmdLogId);

        } catch (Exception e) {
            e.printStackTrace();
            sqlHelper.updateAsync(
                    "update iot_dev_cmd_log set resp_code=0,resp_ctx='"+e.getLocalizedMessage()+"' where id=" + cmdLogId);
        }finally {
            sqlHelper.updateAsync(
                    "update iot_dev_cmd_log set resp_time=now() where id=" + cmdLogId);
        }




        return;
    }

    @Override
    public Integer getDevId() {
        return this.devId;
    }


    private class OpenFailException extends Exception {
        public OpenFailException(String s) {
            super(s);
        }
    }
}
